
package com.example.devecohp;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;

/**
 * The entry point for batch audit that allow the user to audit all files in a folder
 */
public class AuditAllFiles extends AnAction {
    /**
     * The entry point for audit all files
     * @param anActionEvent an AnActionEvent containing information about the action
     */
    @Override
    public void actionPerformed(@NotNull AnActionEvent anActionEvent) {

        VirtualFile virtualFile=anActionEvent.getData(CommonDataKeys.VIRTUAL_FILE);
        if(virtualFile==null){
            return;
        }
        PsiDirectory directory = PsiManager.getInstance(anActionEvent.getProject()).findDirectory(virtualFile);
        List<PsiFile> allFiles;
        if(directory==null){
            allFiles = new ArrayList<>();
            PsiFile file = PsiManager.getInstance(anActionEvent.getProject()).findFile(virtualFile);
            if(file!=null){
                allFiles.add(file);
            }else {
                return;
            }
        }else {
            allFiles = getAllFiles(directory);
        }
        //List<String> filenames = new ArrayList<>();


        Application app = ApplicationManager.getApplication();
        ToolWindowInfo toolWindowInfo = PageManager.getInstance(anActionEvent.getProject()).getToolWindowInfo();
        toolWindowInfo.clear();
        PageManager.getInstance(anActionEvent.getProject()).setModeKeep();

        final int[] count = {0};
        //for(PsiFile f:allFiles){

            Auditor.runAndCreatePageInfo(anActionEvent.getProject(), allFiles, new Auditor.createPageInfoCallback() {
                @Override
                public void run(PageInfo pageInfo) {
                    app.invokeLater(() -> {
                        DumbService.getInstance(anActionEvent.getProject()).runWhenSmart(() -> {
                            count[0] = count[0] + 1;
                            if (pageInfo != null) {
                                toolWindowInfo.addNodeForPage(pageInfo);
                                toolWindowInfo.reloadTree();
                            }
                            if (count[0] >= allFiles.size()) {
                                toolWindowInfo.expandAll();
                                MyToolWindowFactory.updateUpperPanel(anActionEvent.getProject());
                                PageManager.getInstance(anActionEvent.getProject()).filterAllRules(toolWindowInfo.filterTextField.getText());
                            }


                        });
                    });
                }

                @Override
                public void onCancle() {
                    count[0]=allFiles.size();
                }
            }, false);

        //}


    }

    /**
     *
     * @param dir a PsiDirectory serve as the root of the search
     * @return all file in dir that end with .ts, .ets and .js
     */
    public static List<PsiFile> getAllFiles(PsiDirectory dir){
        List<PsiFile> result = new ArrayList<>();
        for(PsiElement element:dir.getChildren()){
            if(element instanceof PsiDirectory){
                result.addAll(getAllFiles((PsiDirectory)element));
            }else if(element instanceof PsiFile){
                if(((PsiFile)element).getName().endsWith(".ts")||((PsiFile)element).getName().endsWith(".ets")||((PsiFile)element).getName().endsWith(".js")){
                    if(!ConfigHelper.isConfigFile((PsiFile) element)) {
                        result.add((PsiFile) element);
                    }
                }
            }
        }
        return result;
    }
}
